package com.myk.game.gobangchess.rooms;

import com.myk.game.gobangchess.constants.BoardStyleData;
import com.myk.game.gobangchess.constants.ColorCost;
import com.myk.game.gobangchess.constants.WinMode;
import com.myk.game.gobangchess.signs.ColorSign;
import com.myk.game.gobangchess.signs.TextSign;
import com.myk.game.gobangchess.utils.GridsUtils;
import com.myk.game.gobangchess.Room;

import java.util.ArrayList;
import java.util.List;

/**
 * 《马踏连星》
 */
public class HorseStepStarRoom extends Room {

    private int newIndex = -1;//最近落子位置
    private final List<Integer> turnIndexList = new ArrayList<>(); //最近被翻转的棋子

    public HorseStepStarRoom(String roomName) {
        super(roomName, "sng玩家的经典作品", "马踏连星", BoardStyleData.getGoBangStyle(14, 14), true, true, "连五胜");
    }

    @Override
    public String getRuleText() {
        return "《马踏连星-规则》\n" +
                "黑白双方轮流各下一个棋子。\n" +
                "落子后马步位置的对方棋子将被翻转为本方棋子。\n" +
                "当一方形成直线或斜线紧密相连的六（or五）连或以上的连线时，若对方下一步不能通过翻转切断这条连线，则形成连线的一方获胜。";
    }

    @Override
    public String getGameInfo() {
        signList.clear();
        if (newIndex != -1) {
            signList.add(new ColorSign(newIndex, ColorCost.NEW_PUT_POINT_LIGHT));
        }
        if (turnIndexList.size() > 0) {
            signList.add(new ColorSign(turnIndexList, ColorCost.GRAY_TRANSLUCENT));
        }
        showShowRemainingCountTip();
        return super.getGameInfo();
    }

    private void showShowRemainingCountTip() {
        for (int i = 0; i < curGrids.length; i++) {
            for (int j = 0; j < curGrids[i].length; j++) {
                if (curGrids[i][j] != 0) {
                    int remainingCount = getRemainingCount(i, j);
                    if (remainingCount > 0) {
                        signList.add(new TextSign(getIndex(i, j), String.valueOf(remainingCount), ColorCost.NEW_PUT_POINT_LIGHT));
                    }
                }
            }
        }
    }

    private int getRemainingCount(int i, int j) {
        int count = 0;
        int[][] dxdys = new int[][]{{-2, -1}, {-2, 1}, {-1, -2}, {-1, 2}, {1, -2}, {1, 2}, {2, -1}, {2, 1}};
        for (int[] dxdy : dxdys) {
            if (isValidMove(i + dxdy[0], j + dxdy[1])) {
                if (curGrids[i + dxdy[0]][j + dxdy[1]] == 0) {
                    count++;
                }
            }
        }
        return count;
    }

    @Override
    public void resetGrids() {
        super.resetGrids();
        newIndex = -1;
        turnIndexList.clear();
    }

    @Override
    public void doRule(int row, int col, int value) {
        if (curGrids[row][col] == 0) { //只能落在空位置
            curGrids[row][col] = value; //实际落子
            newIndex = getIndex(row, col);
            stepAdd(); //增加步数统计
            change(row, col, value);
            checkWin(value);
        }
    }

    private void change(int row, int col, int value) {
        turnIndexList.clear();
        int[][] moves = {{-2, 1}, {-1, 2}, {1, 2}, {2, 1}, {2, -1}, {1, -2}, {-1, -2}, {-2, -1}};
        for (int[] move : moves) {
            int nextRow = row + move[0];
            int nextCol = col + move[1];
            if (isValidMove(nextRow, nextCol) && curGrids[nextRow][nextCol] == getTurnValue(value)) {
                curGrids[nextRow][nextCol] = value;
                turnIndexList.add(getIndex(nextRow, nextCol));
            }
        }
    }

    private void checkWin(int value) {
        //我方落子后对方还有棋连6
        if (checkFormation(getTurnValue(value), isCurMode("连五胜") ? 5 : 6) > 0) {
            if (value == 1) {
                doOver(WinMode.WHITE_WIN, player_white.getNickNameOrTemp() + "执白棋战胜" + player_black.getNickNameOrTemp());
            }
            else {
                doOver(WinMode.BLACK_WIN, player_black.getNickNameOrTemp() + "执黑棋战胜" + player_white.getNickNameOrTemp());
            }
        }
        //没有空位
        else if (GridsUtils.getDataCount(curGrids, 0) == 0) {
            doOver(WinMode.BOTH_DRAW, player_black.getNickNameOrTemp() + "-黑棋战平" + player_white.getNickNameOrTemp() + "-白棋");
        }
        //否则换人继续落子
        else {
            if (cur == 1) {
                noticeWhiteMove();
            }
            else if (cur == 2) {
                noticeBlackMove();
            }
        }
    }

    private int getTurnValue(int value) {
        return value == 1 ? 2 : 1;
    }

    private boolean isValidMove(int r, int c) {
        return (r >= 0 && r < curGrids.length && c >= 0 && c < curGrids[0].length);
    }

    private int checkFormation(int value, int winLength) {
        int rows = curGrids.length;
        int cols = curGrids[0].length;
        int formationCount = 0;

        // 水平方向
        for (int i = 0; i < rows; i++) {
            for (int j = 0; j < cols - winLength + 1; j++) {
                int length = 0;
                for (int k = j; k < j + winLength; k++) {
                    if (curGrids[i][k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= winLength) {
                    formationCount += (length - winLength + 1);
                }
            }
        }

        // 垂直方向
        for (int i = 0; i < rows - winLength + 1; i++) {
            for (int j = 0; j < cols; j++) {
                int length = 0;
                for (int k = i; k < i + winLength; k++) {
                    if (curGrids[k][j] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= winLength) {
                    formationCount += (length - winLength + 1);
                }
            }
        }

        // 左上到右下方向
        for (int i = 0; i < rows - winLength + 1; i++) {
            for (int j = 0; j < cols - winLength + 1; j++) {
                int length = 0;
                for (int k = 0; k < winLength; k++) {
                    if (curGrids[i + k][j + k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= winLength) {
                    formationCount += (length - winLength + 1);
                }
            }
        }

        // 右上到左下方向
        for (int i = 0; i < rows - winLength + 1; i++) {
            for (int j = winLength - 1; j < cols; j++) {
                int length = 0;
                for (int k = 0; k < winLength; k++) {
                    if (curGrids[i + k][j - k] == value) {
                        length++;
                    }
                    else {
                        break;
                    }
                }
                if (length >= winLength) {
                    formationCount += (length - winLength + 1);
                }
            }
        }

        return formationCount;
    }

}
